﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using TheMovieDB;
using System.IO;
using System.Xml;
using System.Reflection;

namespace MovieDB
{
    public partial class FrmMovieDbMain : Form
    {
        List<Image> imgList = new List<Image>();
        TmdbAPI tmdb = new TmdbAPI("23a30e31f9e1b0a2394b43c32928e408");
        StringBuilder log = new StringBuilder();
        List<MdbMovie> movieSearchList = new List<MdbMovie>();
        MdbOptions options = new MdbOptions();
        
        public FrmMovieDbMain()
        {
            InitializeComponent();
        }

        private void FrmMovieDbMain_Load(object sender, EventArgs e)
        {
            // Optionen und Plugins werden erst in der nächsten Version eingeführt
            //
            // this.LoadPlugins();
            if (this.options.MissingCriticalInformation)
            {
                FrmOptions frmOptions = new FrmOptions(this.options);
                frmOptions.ShowDialog();
            }
        }

        private void LoadPlugins()
        {
            List<IPlugin> list = MdbUtils.GetMovieDbPlugins("plugins");

            foreach (IPlugin plug in list)
            {
                this.pluginsToolStripMenuItem.DropDownItems.Add(plug.GetMenuItems());
            }
        }

        private void ScanDir(string path)
        {
            if (Directory.Exists(path))
            {
                this.clbMovieListBox.Items.Clear();
                foreach (string dir in Directory.GetDirectories(this.txtFolder.Text))
                {
                    MdbMovie movie = new MdbMovie(dir, tmdb);
                    this.clbMovieListBox.Items.Add(movie);

                    if (!movie.HasMovieXml || !movie.HasFolderJpg || !movie.HasFanartJpg)
                    {
                        this.clbMovieListBox.SetItemChecked(this.clbMovieListBox.Items.Count - 1, true);
                    }
                }

                this.log.AppendLine("Im Verzeichnis " + this.txtFolder.Text + " wurden " + this.clbMovieListBox.Items.Count + " Ordner gefunden");
                this.log.AppendLine("Davon fehlen in " + this.clbMovieListBox.CheckedItems.Count + " Ordner Informationen");
            }
        }

        private void Search()
        {
            this.movieSearchList.Clear();
            this.log = new StringBuilder();
            foreach (MdbMovie movie in this.clbMovieListBox.CheckedItems)
            {
                this.log.AppendLine("Suche nach Informationen über " + movie.Name );
                this.movieSearchList.Add(movie);

                if (File.Exists(movie.Path + "\\movie.xml"))
                {

                    XmlDocument doc = new XmlDocument();
                    doc.Load(movie.Path + "\\movie.xml");

                    if (doc.GetElementsByTagName("id").Count > 0)
                    {
                        string imdbId = doc.GetElementsByTagName("id")[0].InnerText;

                        if (imdbId != string.Empty)
                        {


                            this.log.AppendLine(" -> movie.xml existiert - Suche über imdb ID: " + imdbId);
                            movie.GetMovieInfos(imdbId);
                        }
                        else
                        {
                            this.log.AppendLine(" -> Suche über Ordnerbezeichnung");
                            movie.GetMovieInfos();
                        }
                    }
                }
                else
                {
                    this.log.AppendLine(" -> Suche über Ordnerbezeichnung");
                    movie.GetMovieInfos();
                }

                // Wenn nur ein Ergebnis gefunden wir werden die Daten direkt geladen
                if (movie.Current != null)
                {
                    this.log.AppendLine(" -> Es wurde nur ein Ergebnis gefunden.");
                    this.log.AppendLine(" -> Automatischer Download der Informationen");

                    try
                    {
                        MdbUtils.CreateMovieXml(movie.Current).Save(movie.Path + "\\movie.xml");

                        MdbUtils.SaveImage(movie, TmdbImageType.backdrop, "fanart.jpg", "database");

                        MdbUtils.SaveImage(movie, TmdbImageType.poster, "folder.jpg", "database");
                    }
                    catch (Exception e)
                    {
                        this.log.AppendLine(" -> Fehler. Film wird manuell abgefragt");
                        movie.Current = null;
                    }
                }
                else
                {
                    if (movie.Possibilities == null || movie.Possibilities.Length == 0)
                    {
                        this.log.AppendLine(" -> Es wurden keine Ergebnisse gefunden");
                        this.log.AppendLine(" -> Zusätzliche Informationen werden später abgefragt");
                    }
                    else
                    {
                        this.log.AppendLine(" -> Es wurden " + movie.Possibilities.Length + " Ergebnisse gefunden");
                        this.log.AppendLine(" -> Informationen werden später geladen");
                    }
                }
            }

            // Wurden mehrere Ergebnisse gefunden werden sie der reihe nach abgearbeitet
            foreach (MdbMovie movie in this.movieSearchList)
            {
                if(movie.Possibilities != null && movie.Possibilities.Length > 1)
                {
                    this.log.AppendLine("Erfrage Informationen für " + movie.Name);
                    FrmResultSelect frm = new FrmResultSelect(movie, this.log, this.tmdb);
                    frm.MovieSelected += new EventHandler(frm_MovieSelected);
                    frm.ShowDialog();
                }
            }
        }

        /// <summary>
        /// Initialisiert die Detailansicht mit den Daten, die über den Film vorhanden sind
        /// </summary>
        /// <param name="movie"></param>
        private void initView(MdbMovie movie)
        {
            ImageList posterList = new ImageList();

            // Ansicht zunächst aufräumen
            this.txtName.Text = movie.Name;
            this.txtId.Text = string.Empty;
            this.txtPlot.Text = string.Empty;
            this.txtYear.Text = string.Empty;
            this.pcbPoster.Image = null;
            this.pcbBackdrop.Image = null;
            this.pbRating.Value = 0;

            // Wenn ein Cover Bild vorhanden ist -> laden
            if (movie.HasFolderJpg)
            {
                FileStream fs = new FileStream(movie.Path + "\\folder.jpg", FileMode.Open);
                Image img = Image.FromStream(fs);
                Rectangle newRect = ImageUtils.GetScaledRectangle(img, pcbPoster.ClientRectangle);

                this.pcbPoster.Image = ImageUtils.GetResizedImage(img, newRect);
                img.Dispose();
                fs.Close();
            }

            // Wenn ein Backdrop vorhanden ist -> laden
            if (movie.HasFanartJpg)
            {

                FileStream fs = new FileStream(movie.Path + "\\fanart.jpg", FileMode.Open);
                Image img = Image.FromStream(fs);
                Rectangle newRect = ImageUtils.GetScaledRectangle(img, pcbBackdrop.ClientRectangle);

                this.pcbBackdrop.Image = ImageUtils.GetResizedImage(img, newRect);
                img.Dispose();
                fs.Close();
            }

            // Wenn eine Movie XML vorhanden ist -> Infos laden
            if (movie.HasMovieXml)
            {
                XmlDocument doc = new XmlDocument();
                int rating = 0;
                doc.Load(movie.Path + "\\movie.xml");

                this.txtYear.Text = doc.GetElementsByTagName("year")[0].InnerText;
                this.txtPlot.Text = doc.GetElementsByTagName("plot")[0].InnerText;
                this.txtName.Text = doc.GetElementsByTagName("title")[0].InnerText;
                this.txtId.Text = doc.GetElementsByTagName("id")[0].InnerText;

                rating = Convert.ToInt32(Convert.ToDouble(doc.GetElementsByTagName("rating")[0].InnerText));

                this.pbRating.Value = rating;
            }

            // Wenn für den Film ein Datenbankverzeichnis existiert werden die vorhandenen Cover
            // in eine ImageList geladen
            if (Directory.Exists(@"Database\\" + txtId.Text + "\\images\\Poster"))
            {
                // Die ImageList wird dem ListView lstPoster zugeordnet
                this.lstPoster.View = View.LargeIcon;
                posterList.ImageSize = new Size(90, 130);
                this.lstPoster.LargeImageList = posterList;
                this.lstPoster.Items.Clear();

                foreach (string file in Directory.GetFiles(@"Database\\" + txtId.Text + "\\images\\Poster"))
                {
                    try
                    {
                        // Bild in Imageliste einlesen
                        FileStream fs = new FileStream(file, FileMode.Open);
                        Image tmpImg = Image.FromStream(fs);
                        posterList.Images.Add(tmpImg);
                        fs.Close();

                        // und dem ListView zuordnen
                        ListViewItem poster = new ListViewItem();
                        poster.ImageIndex = posterList.Images.Count - 1;
                        poster.Text = tmpImg.Width.ToString() + "x" + tmpImg.Height.ToString();
                        this.lstPoster.Items.Add(poster);
                    }
                    catch
                    {
                        
                    }
                }
            }
        }

        /// <summary>
        /// Selektiert alle Items in clbMovieList mit dem Übergebenen Status
        /// </summary>
        /// <param name="state">Der Status mit dem selektiert werden soll</param>
        private void MovieListSelect(bool state)
        {
            CheckState cs = state ? CheckState.Checked : CheckState.Unchecked;

            for (int i = 0; i < this.clbMovieListBox.Items.Count; i++)
            {
                this.clbMovieListBox.SetItemCheckState(i, cs);
            }
        }

        void frm_MovieSelected(object sender, EventArgs e)
        {
            MdbMovie movie = ((MdbMovie)sender);

            this.log.AppendLine(" -> " + movie.Current.Name + " wurde als Ergebnis für " + movie.Name + " ausgewählt");
            this.log.AppendLine(" -> Download der Informationen");
            
            MdbUtils.CreateMovieXml(movie.Current).Save(movie.Path + "\\movie.xml");

            MdbUtils.SaveImage(movie, TmdbImageType.backdrop, "fanart.jpg", "database");

            MdbUtils.SaveImage(movie, TmdbImageType.poster, "folder.jpg", "database");
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            this.fbdMovieFolder.ShowDialog();
            this.txtFolder.Text = this.fbdMovieFolder.SelectedPath;
            this.ScanDir(this.txtFolder.Text);
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            if (Directory.Exists(this.txtFolder.Text))
            {
                DateTime startTime = DateTime.Now, endTime;
                TimeSpan duration;

                this.statusLabel.Text = "Suche gestartet";

                this.Search();
                endTime = DateTime.Now;
                duration = endTime - startTime;
                this.statusLabel.Text = "Suche beendet, nach " + duration.ToString();

                this.log.AppendLine("Die Suche wurde in " + duration.ToString() + " abgeschlossen");
                new FrmLog(this.log.ToString()).Show();
                this.ScanDir(this.txtFolder.Text);
            }
        }

        private void clbMovieListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            MdbMovie movie = (MdbMovie)((CheckedListBox)sender).SelectedItem;

            this.initView(movie);
        }

        private void btnUndo_Click(object sender, EventArgs e)
        {
            MdbMovie movie = (MdbMovie)clbMovieListBox.SelectedItem;

            this.initView(movie);
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            MdbMovie movie = (MdbMovie)clbMovieListBox.SelectedItem;
            XmlDocument doc = null;

            if (File.Exists(movie.Path + "\\movie.xml"))
            {
                doc = new XmlDocument();
                doc.Load(movie.Path + "\\movie.xml");
            }

            if (doc != null)
            {
                doc.GetElementsByTagName("title")[0].InnerText = this.txtName.Text;
                doc.GetElementsByTagName("year")[0].InnerText = this.txtYear.Text;
                doc.GetElementsByTagName("plot")[0].InnerText = this.txtPlot.Text;
                doc.GetElementsByTagName("id")[0].InnerText = this.txtId.Text;

                doc.Save(movie.Path + "\\movie.xml");
            }
        }

        private void txtFolder_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                this.ScanDir(this.txtFolder.Text);
            }
        }

        private void btnSelectAll_Click(object sender, EventArgs e)
        {
            this.MovieListSelect(true);
        }

        private void btnSelectNone_Click(object sender, EventArgs e)
        {
            this.MovieListSelect(false);
        }

        private void beendenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new FrmAbout().Show();
        }

    }
}
